// Copyright (c) 2009, Philip Tucker
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the <organization> nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY Philip Tucker 'AS IS' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL Philip Tucker BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.honkentuber.android;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import android.graphics.drawable.Drawable;
import android.location.Address;

/**
 * Tracks queries and results by type. Caller can use isComplete() and 
 * nextQuery() to iterate over queries, and reset() to clear results before 
 * performing a new search.
 */
public class MapSearch {

  /**
   * Once we get this number of results for each type, we stop searching.
   */
  private final static int MAX_RESULTS = 5;

  private final int type;

  private final List<String> queries;

  private Iterator<String> queryIterator;

  private final List<MapItem> results =
      new ArrayList<MapItem>();

  private final String title;

  private final Drawable marker;

  private final MapItems allItems;

  private final String toStringValue;

  public MapSearch(int type, String title,
      Drawable marker, List<String> queries, MapItems allItems) {
    this.type = type;
    this.title = title;
    this.marker = marker;
    this.queries = Collections.unmodifiableList(queries);
    this.queryIterator = this.queries.iterator();
    this.allItems = allItems;
    this.toStringValue = type + ":" + title + ":" + queries;
  }

  public int getType() {
    return type;
  }

  public String getTitle() {
    return title;
  }

  public Drawable getMarker() {
    return marker;
  }

  /**
   * Add new addresses up to our max number of addresses. Also, discard
   * duplicates (based on lat,lon) across all allItems.
   * 
   * @param locations New locations to add.
   * @return Locations actually added.
   */
  public List<SearchResultMapItem> addResults(Iterable<Address> addresses) {
    int maxNumberToAdd = MAX_RESULTS - results.size();

    List<SearchResultMapItem> newResults =
        new ArrayList<SearchResultMapItem>(maxNumberToAdd);
    Iterator<Address> iter = addresses.iterator();
    while (newResults.size() < maxNumberToAdd && iter.hasNext()) {
      Address address = iter.next();
      if (allItems.addSearchResult(address)) {
        newResults.add(new SearchResultMapItem(this, address));        
      }
    }

    results.addAll(newResults);
    return Collections.unmodifiableList(newResults);
  }

  public void reset() {
    results.clear();
    queryIterator = queries.iterator();
  }

  /**
   * @return True if we have our max results, or we have no more queries.
   */
  public boolean isComplete() {
    return (results.size() >= MAX_RESULTS) || !queryIterator.hasNext();
  }

  /**
   * @return Next query if one is available and we have not yet reached our max
   *         results. Otherwise, null.
   */
  public String nextQuery() {
    if (isComplete()) {
      return null;
    }
    return queryIterator.next();
  }

  @Override
  public String toString() {
    return toStringValue;
  }
}